package tech.popsoft.cip.manage.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.popsoft.cip.message.common.entity.RequestMessage;
import tech.popsoft.cip.message.common.entity.ResponseMessage;
import tech.popsoft.cip.message.common.enums.ApiMessageStatusEnum;
import tech.popsoft.cip.message.common.enums.MessageResponseResultEnum;
import tech.popsoft.cip.message.common.enums.MessageStatusEnum;
import tech.popsoft.cip.config.AppConfig;
import tech.popsoft.cip.manage.exception.ApiMessageLogExceptionEnum;
import tech.popsoft.cip.manage.service.ApiMessageLogService;
import tech.popsoft.platform.common.base.BaseServiceImpl;
import tech.popsoft.platform.common.exception.CustomException;
import tech.popsoft.cip.manage.entity.ApiMessageLog;
import tech.popsoft.cip.manage.mapper.ApiMessageLogMapper;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 消息日志 服务实现类
 * @author wqliu
 * @date 2021-08-21
 *
 */
@Service
public class ApiMessageLogServiceImpl extends BaseServiceImpl<ApiMessageLogMapper, ApiMessageLog> implements ApiMessageLogService {
    @Autowired
    private AppConfig appConfig;


    /**
     * 默认查询消息数量
     */
    private final int DEFAULT_QUERY_MESSAGE_COUNT = 5;
    /**
     * 最大查询消息数量
     */
    private final int MAX_QUERY_MESSAGE_COUNT = 20;

    @Override
    public ApiMessageLog init() {
        ApiMessageLog entity=new ApiMessageLog();

        return entity;
    }

    @Override
    public boolean checkRequestMessageExist(String requestMessageId) {
        Integer count = this.lambdaQuery().eq(ApiMessageLog::getRequestId, requestMessageId).count();
        return count.intValue()>0;

    }

    @Override
    public boolean checkResponseMessageExist(String responseMessageId) {
        Integer count = this.lambdaQuery().eq(ApiMessageLog::getResponseId, responseMessageId).count();
        return count.intValue()>0;
    }

    @Override
    public ApiMessageLog getByRequestMessageId(String requestMessageId) {
        List<ApiMessageLog> list = this.lambdaQuery().eq(ApiMessageLog::getRequestId, requestMessageId).list();
        if(CollectionUtils.isNotEmpty(list)){
            return list.get(0);
        }else{
            throw new CustomException(ApiMessageLogExceptionEnum.MESSAGE_LOG_NOT_EXIST);
        }
    }

    @Override
    public void updateStatus(String status, String messageId) {
        ApiMessageLog apiMessageLog =getByRequestMessageId(messageId);
        apiMessageLog.setStatus(status);
        modify(apiMessageLog);
    }

    @Override
    public void incrementSendCount(String messageId) {
        ApiMessageLog apiMessageLog =getByRequestMessageId(messageId);
        apiMessageLog.setSendCount(apiMessageLog.getSendCount()+1);
        modify(apiMessageLog);
    }

    @Override
    public ApiMessageLog createRequestPart(RequestMessage message,String responseAppCode) {

        ApiMessageLog log = new ApiMessageLog();
        log.setRequestId(message.getId());
        log.setRequestAppCode(message.getPublishAppCode());
        log.setRequestTopicCode(message.getTopic());
        log.setRequestTime(LocalDateTime.now());
        log.setRequestData(message.getContent());
        log.setResponseAppCode(responseAppCode);
        //发送次数设置为0
        log.setSendCount(0);
        add(log);
        return log;

    }

    @Override
    public ApiMessageLog createRequestPart(RequestMessage message) {
        return createRequestPart(message,null);
    }

    @Override
    public void updateResponsePart(ResponseMessage message) {

        ApiMessageLog log = getByRequestMessageId(message.getRequestMessageId());
        //响应消息的发布者，对应请求消息的响应
        log.setResponseAppCode(message.getPublishAppCode());
        log.setResponseTopicCode(message.getTopic());
        log.setResponseTime(LocalDateTime.now());
        log.setResponseData(message.getContent());
        log.setResponseResult(message.getResult());
        log.setErrorMessage(message.getErrorMessage());
        log.setResponseId(message.getId());
        //将消息更新为已响应
        log.setStatus(MessageStatusEnum.RESPONSED.name());

        modify(log);

    }

    @Override
    public List<String> getResendAppList(int maxSendCount) {
        LocalDateTime now=LocalDateTime.now();
        LocalDateTime beforeNow = now.minusSeconds(15);
        try {
            LambdaQueryChainWrapper<ApiMessageLog> query = this.lambdaQuery()
                    //消息状态为待发送或已发送
                    .and(x -> x.eq(ApiMessageLog::getStatus, MessageStatusEnum.WAIT_REQUEST.name())
                            .or(y -> y.eq(ApiMessageLog::getStatus, MessageStatusEnum.REQUESTED.name())))
                    // 排除掉登录请求
                    .ne(ApiMessageLog::getRequestTopicCode, "framework.login.request")
                    //发送方为消息服务中心
                    .eq(ApiMessageLog::getRequestAppCode,appConfig.getMessage().getMessageServerAppCode())
                    //发送次数小于设置的最大发送次数
                    .lt(ApiMessageLog::getSendCount, maxSendCount)
                    //请求时间小于当前时间15秒，避免刚产生的消息尚未收到服务端响应时就进行重发
                    .lt(ApiMessageLog::getRequestTime, beforeNow)
                    //按照响应应用编码分组
                    .groupBy(ApiMessageLog::getResponseAppCode)
                    //只查询应用编码
                    .select(ApiMessageLog::getResponseAppCode);

            List<ApiMessageLog> list = query.list();
            if(CollectionUtils.isNotEmpty(list)){
                return list.stream().map(x->x.getResponseAppCode()).collect(Collectors.toList());
            }else{
                return null;
            }

        }catch (Exception e) {
            log.error("获取需要重发消息的应用列表出错",e);
            return null;
        }
    }

    @Override
    public List<ApiMessageLog> getResendMessage(int messageCount,int maxSendCount,String appCode) {
        LocalDateTime now=LocalDateTime.now();
        LocalDateTime beforeNow = now.minusSeconds(15);
        try {
            LambdaQueryChainWrapper<ApiMessageLog> query = this.lambdaQuery()
                    //消息状态为待发送或已发送
                    .and(x -> x.eq(ApiMessageLog::getStatus, MessageStatusEnum.WAIT_REQUEST.name())
                            .or(y -> y.eq(ApiMessageLog::getStatus, MessageStatusEnum.REQUESTED.name())))
                    // 排除掉登录请求
                    .ne(ApiMessageLog::getRequestTopicCode, "framework.login.request")
                    //发送方为消息服务中心
                    .eq(ApiMessageLog::getRequestAppCode,appConfig.getMessage().getMessageServerAppCode())
                    //指定响应应用编码
                    .eq(ApiMessageLog::getResponseAppCode,appCode)
                    //发送次数小于设置的最大发送次数
                    .lt(ApiMessageLog::getSendCount, maxSendCount)
                    //请求时间小于当前时间15秒，避免刚产生的消息尚未收到服务端响应时就进行重发
                    .lt(ApiMessageLog::getRequestTime, beforeNow)
                    //按照请求时间升序排列
                    .orderByAsc(ApiMessageLog::getRequestTime)
                    //只取指定数量的消息
                    .last("limit " + messageCount);


            return query.list();
        }catch (Exception e) {
            log.error("获取发送信息失败",e);
            return null;
        }
    }

    @Override
    public List<ApiMessageLog> queryWaitHandleMessages(int count,String appCode) {
        //处理消息数量，如为0，默认设置默认数量，如超出最大数量，则置为最大数量
        if (count == 0) {
            count = DEFAULT_QUERY_MESSAGE_COUNT;
        } else if (count > MAX_QUERY_MESSAGE_COUNT) {
            count = MAX_QUERY_MESSAGE_COUNT;
        }

        List<ApiMessageLog> list = this.lambdaQuery()
                .select(ApiMessageLog::getRequestId,ApiMessageLog::getRequestTopicCode,ApiMessageLog::getRequestData,ApiMessageLog::getRequestTime)
                .eq(ApiMessageLog::getStatus, ApiMessageStatusEnum.WAIT_HANDLE.name())
                .eq(ApiMessageLog::getResponseAppCode, appCode)
                .orderByAsc(ApiMessageLog::getRequestTime)
                //只取指定数量的消息
                .last("limit " + count)
                .list();
        return list;


    }

    @Override
    public void confirm(String requestMessageId, String appCode) {

        //获取消息日志对象
        ApiMessageLog log = getByRequestMessageId(requestMessageId);
        //判断是否有权限对本消息确认
        if(!appCode.equals(log.getResponseAppCode())){
            throw new CustomException(ApiMessageLogExceptionEnum.MESSAGE_CONFIRM_PERMISSION_ERROR);
        }

        //更新消息日志
        log.setStatus(ApiMessageStatusEnum.HANDLED.name());
        log.setResponseResult(MessageResponseResultEnum.SUCCESS.name());
        log.setResponseTime(LocalDateTime.now());
        //更新日志
        modify(log);

    }


}
